/**
 * 
 */
package it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.actions;


import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.events.EndActionEvent;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.events.EventManager;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.events.NoActionEvent;

import java.util.LinkedList;
import java.util.Map;

/**
 * @author Massimo Canonaco
 */
public class ActionMediator 
{
	/**This action does nothing. */
	static private final GenericLogicAction NO_ACTION = new GenericLogicAction() {
		
		@Override
		public void reset() 
		{
			
		}
		
		@Override
		public boolean isFinished() 
		{
			return true;
		}
		
		@Override
		public float getActionIdentifier() {
			return -1;
		}
		
		@Override
		public boolean execute(LinkedList<GenericActionInfo> infos) 
		{
			return true;
		}
		
		public String getName() 
		{
			return "noaction";
		};
	};
	
	/** */
	private boolean free;
	
	/**Contains all the actions. */
	private Map<Float, GenericLogicAction> actionProvider;
	
	/**Contains all the informations which can be used for actions. In this way there isn't necessity of creating <i>new<i/> informations every time, but we can create once and re-use them. */
	private Map<Float, GenericActionInfo> infoProvider;
	
	/**Contains all the informations for the actual/current action. */
	private LinkedList<GenericActionInfo> actionInfo;
	
	/**It's the current/selected action. */
	private GenericLogicAction currentAction;
	
	/** */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public ActionMediator(Map actions, Map informations)
	{
		currentAction = NO_ACTION;
		actionInfo = new LinkedList<>();
		actionProvider = actions;
		infoProvider = informations;
		free = true;
	}
	
	/** */
	public void addActionInfo(GenericActionInfo info)
	{
		info.setBusy(true);
		actionInfo.addLast(info);
	}
	
	/** */
	public void addProvidedInfo(GenericActionInfo info)
	{
		GenericActionInfo providedInfo = infoProvider.get(info.getGUID());
		
		if(providedInfo != null && !providedInfo.isBusy())
		{
			providedInfo.setBusy(true);
			actionInfo.addLast(providedInfo);
		}
	}
	
	/** */
	public void addProvidedInfo(final float infoGUID)
	{
		GenericActionInfo providedInfo = infoProvider.get(infoGUID);
		
		if(providedInfo != null && !providedInfo.isBusy())
		{
			providedInfo.setBusy(true);
			actionInfo.addLast(providedInfo);
		}
	}
	
	/** */
	public GenericActionInfo getProvidedInfo(float GUID)
	{
		return infoProvider.get(GUID);
	}
	
	/** */
	public boolean playAction()
	{
//		System.out.println("PLAY ACTION CALL");
		if(currentAction != NO_ACTION)
		{
			boolean execute = currentAction.execute(actionInfo) && currentAction.isFinished();
					System.out.println("execute "+execute+" "+currentAction.getName());
			if(execute && currentAction.isFinished())
			{
				currentAction.reset();
				setNoAction();
				EventManager.getInstance().triggerEvent(new EndActionEvent());

			}
			return execute;
		}

		return currentAction.execute(null);
	}
	
	
	/** */
	public void setAction(float GUID)
	{
		System.out.println("imposto action con guid "+GUID);
		GenericLogicAction newAction = actionProvider.get(GUID);
		
		// If the currentAction is finished.
		if(currentAction.isFinished())
//		if(currentAction != newAction && currentAction.isFinished())
		{
//			actionInfo.clear();
			currentAction.reset();
			// Set a new current action.
			if(newAction != null)
			{
			System.out.println("imposto nuova action "+newAction.getName());
				currentAction = newAction;
				currentAction.reset();
			}
//			else
//			{
//				setNoAction();
//			}
//			currentAction = newAction != null ? newAction : NO_ACTION;
		}
//		free = true;
	}
	
	/** */
	public void setNoAction()
	{
		System.out.println("IMPOSTO NOACTION");
		currentAction.reset();
		currentAction = NO_ACTION;
		clearInformations();
		EventManager.getInstance().triggerEvent(new NoActionEvent());
	}

	/**
	 * @return the currentAction
	 */
	public GenericLogicAction getCurrentAction() {
		return currentAction;
	}
	
	/** */
	public void clearInformations()
	{
		actionInfo.clear();
	}
	
	/** */
	public boolean isNoAction()
	{
		return currentAction == NO_ACTION;
	}

	/**
	 * @return the noAction
	 */
	public static GenericLogicAction getNoAction() {
		return NO_ACTION;
	}
}
